"""
Emby演员信息管理工具
功能：管理Emby媒体库中的演员信息，包括查询演员、更新头像等
使用技术：loguru(日志), click(命令行), requests(HTTP请求)
"""

import base64
import json
import os
from pathlib import Path
from typing import Dict, List, Optional, Union
from urllib.parse import quote

import click
import requests
from loguru import logger
from pymediainfo import MediaInfo
from unipath import Path as UniPath, FILES

# 配置日志
logger.add("actor_management.log", rotation="10 MB", retention="30 days", level="INFO")


# ----------------------------------------- 工具函数 -----------------------------------------

def get_base64_str(file_path: Union[str, Path]) -> str:
    """获取文件的base64编码字符串

    Args:
        file_path: 图片文件路径

    Returns:
        base64编码的字符串
    """
    with open(file_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode("utf-8")


def get_actor_info(
        actor_name: str,
        domain: str,
        api_key: str
) -> Optional[Dict]:
    """获取演员的详细信息

    Args:
        actor_name: 演员姓名
        domain: Emby服务器地址
        api_key: Emby API密钥

    Returns:
        演员信息的字典或None(如果查询失败)
    """
    url = f"{domain}/emby/Persons/{quote(actor_name, 'utf-8')}"
    headers = {"accept": "application/json"}
    params = {"api_key": api_key}

    try:
        response = requests.get(url, headers=headers, params=params, timeout=10)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        logger.error(f"获取演员信息失败: {e}")
        return None


def update_actor_image(actor_id: str, image_path: Union[str, Path], domain: str, api_key: str) -> bool:
    """更新演员头像

    Args:
        actor_id: 演员ID
        image_path: 头像图片路径
        domain: Emby服务器地址
        api_key: Emby API密钥

    Returns:
        是否更新成功
    """
    url = f"{domain}/emby/Items/{actor_id}/Images/Primary"
    params = {"api_key": api_key}
    headers = {"Content-Type": "image/jpeg"}

    try:
        image_data = get_base64_str(image_path)
        response = requests.post(
            url,
            headers=headers,
            params=params,
            data=image_data,
            timeout=15
        )
        response.raise_for_status()
        logger.success(f"演员头像更新成功: {actor_id}")
        return True
    except requests.RequestException as e:
        logger.error(f"头像更新失败: {e}")
        return False


def get_all_actors(domain: str, api_key: str) -> List[Dict]:
    """获取所有演员信息

    Args:
        domain: Emby服务器地址
        api_key: Emby API密钥

    Returns:
        演员信息列表
    """
    url = f"{domain}/emby/Persons"
    headers = {"accept": "application/json"}
    params = {"api_key": api_key, "Recursive": "true"}

    try:
        response = requests.get(url, headers=headers, params=params, timeout=15)
        response.raise_for_status()
        return response.json().get("Items", [])
    except requests.RequestException as e:
        logger.error(f"获取演员列表失败: {e}")
        return []


# ----------------------------------------- 命令行功能 -----------------------------------------

@click.group()
@click.option("--domain", default="http://localhost:8096", help="Emby服务器地址")
@click.option("--api-key", required=True, help="Emby API密钥")
@click.pass_context
def cli(ctx, domain: str, api_key: str):
    """演员管理命令行工具"""
    ctx.ensure_object(dict)
    ctx.obj["DOMAIN"] = domain
    ctx.obj["API_KEY"] = api_key


@cli.command()
@click.argument("actor_name")
@click.pass_context
def get_actor(ctx, actor_name: str):
    """查询演员信息"""
    domain = ctx.obj["DOMAIN"]
    api_key = ctx.obj["API_KEY"]

    actor_info = get_actor_info(actor_name, domain, api_key)
    if actor_info:
        click.echo(json.dumps(actor_info, indent=2, ensure_ascii=False))
        logger.info(f"找到演员信息: {actor_name}")
    else:
        logger.warning(f"未找到演员: {actor_name}")


@cli.command()
@click.argument("image_root", type=click.Path(exists=True))
@click.pass_context
def update_all(ctx, image_root: str):
    """更新所有演员头像"""
    domain = ctx.obj["DOMAIN"]
    api_key = ctx.obj["API_KEY"]
    image_root_path = UniPath(image_root)

    # 获取所有演员
    actors = get_all_actors(domain, api_key)
    if not actors:
        logger.error("未获取到演员列表，请检查API配置")
        return

    # 收集所有本地头像文件
    image_map = {}
    for file_path in image_root_path.walk(filter=FILES):
        if file_path.ext.lower() in (".jpg", ".jpeg", ".png"):
            image_map[file_path.stem] = file_path

    # 更新没有头像的演员
    updated_count = 0
    for actor in actors:
        updated_count += 1
        actor_name = actor["Name"]
        actor_id = actor["Id"]

        # 跳过已有头像的演员
        if actor.get("ImageTags"):
            logger.info(f"跳过已有头像的演员: {actor_name}")
            continue

        # 查找匹配的头像
        image_path = image_map.get(actor_name)
        if not image_path:
            logger.warning(f"未找到 {actor_name} 的头像文件")
            continue

        # 更新头像
        update_actor_image(actor_id, image_path, domain, api_key)

    logger.success(f"头像更新完成! 总计更新: {updated_count}/{len(actors)}")


@cli.command()
@click.argument("actor_name")
@click.argument("image_path", type=click.Path(exists=True))
@click.pass_context
def update_one(ctx, actor_name: str, image_path: str):
    """更新单个演员头像"""
    domain = ctx.obj["DOMAIN"]
    api_key = ctx.obj["API_KEY"]

    # 获取演员ID
    actor_info = get_actor_info(actor_name, domain, api_key)
    if not actor_info:
        logger.error(f"演员不存在: {actor_name}")
        return

    # 更新头像
    actor_id = actor_info["Id"]
    if update_actor_image(actor_id, image_path, domain, api_key):
        logger.success(f"{actor_name} 头像更新成功!")
    else:
        logger.error(f"{actor_name} 头像更新失败")


@cli.command()
@click.pass_context
def list_actors(ctx):
    """列出所有演员"""
    domain = ctx.obj["DOMAIN"]
    api_key = ctx.obj["API_KEY"]

    actors = get_all_actors(domain, api_key)
    if not actors:
        logger.error("未获取到演员列表")
        return

    click.echo(f"找到 {len(actors)} 位演员:")
    for idx, actor in enumerate(actors, 1):
        has_image = "有" if actor.get("ImageTags") else "无"
        click.echo(f"{idx}. {actor['Name']} (ID: {actor['Id']}, 头像: {has_image})")


# ----------------------------------------- 主函数 -----------------------------------------

"""
# 查看帮助
python person_util.py --help

# 查询演员信息
python person_util.py --api-key=your_api_key get_actor "演员姓名"

# 更新所有演员头像（从指定目录）
python person_util.py --api-key=your_api_key update_all /path/to/images
python person_util_ai.py --api-key="ac09e924c9f443fd95b6300ab4ab4ac0" --domain="http://localhost:8096" update-all "E:/emby/video_actor_pic/pic"

# 更新单个演员头像
python person_util.py --api-key=your_api_key update_one "演员姓名" /path/to/image.jpg

# 列出所有演员
python person_util.py --api-key=your_api_key list_actors

文档完善：

所有函数添加docstring
参数说明和返回类型
命令行帮助文档

"""
if __name__ == "__main__":
    cli()
